package com.tg.app.activity.device.settings;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.TextView;

import androidx.annotation.ColorRes;
import androidx.core.util.Consumer;

import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.demo.view.RecordAudioView;
import com.tange.base.toolkit.FileUtil;
import com.tange.core.device.facade.ConnectStatus;
import com.tange.core.device.facade.DeviceFacade;
import com.tange.core.device.facade.Instruction;
import com.tange.core.device.facade.Status;
import com.tg.app.R;
import com.tg.app.activity.base.DeviceSettingsBaseActivity;
import com.tg.app.activity.device.DeviceSettingsActivity;
import com.tg.app.camera.AVIOCTRLDEFs;
import com.tg.app.helper.AlertSoundHelper;
import com.tg.app.helper.AppHelper;
import com.tg.app.view.AlertPersonalSoundItemView;
import com.tg.app.view.MsgCenterToast;
import com.tg.appcommon.android.AlarmUtil;
import com.tg.appcommon.android.LanguageUtils;
import com.tg.appcommon.android.PermissionUtil;
import com.tg.appcommon.android.ResourcesUtil;
import com.tg.appcommon.android.TGAlertDialog;
import com.tg.appcommon.android.TGApplicationBase;
import com.tg.appcommon.android.TGLog;
import com.tg.appcommon.android.TGToast;
import com.tg.data.bean.DeviceSettingsInfo;
import com.tg.data.helper.SoundHelper;
import com.tg.data.http.entity.AlarmToneCapBean;
import com.tg.data.media.AudioRecorder;
import com.tg.data.media.G711A;
import com.tg.data.media.OnICameraRecordListener;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;

public class CustomAlertSoundActivity extends DeviceSettingsBaseActivity implements RecordAudioView.IRecordAudioListener {
    private static final String TAG = "CustomAlertSoundActivity";
    private AudioRecorder audioRecorder;
    boolean hasAudioPermission;

    private OnICameraRecordListener recordListener;
    private long recorderStartTime;
    private long recorderTime;
    private boolean isCompleted;
    private int audioCodecs = 0;
    private String mFrom;
    private AlertPersonalSoundItemView mAlertPersonalSoundItemView;

    private SoundHelper soundHelper;
    private DeviceSettingsInfo info;
    private DeviceFacade deviceFacade;

    @Override
    protected void onSetupFailed() {
        hideLoading();
    }

    @Override
    public boolean shouldSetStatusBarColor() {
        return true;
    }

    private final Consumer<ConnectStatus> connectStatusConsumer = connectStatus -> {
        if (connectStatus.getStatus() == Status.SUCCESS){
            TGLog.d(TAG,"连接成功");
            AppHelper.sendIOCtrl(deviceFacade, AVIOCTRLDEFs.TCI_CMD_GET_ALARMTONE_CAP_REQ, new byte[4]);
        }else if (connectStatus.getStatus() == Status.FAILED){
            TGLog.d(TAG,"连接失败");
        }
    };

    private final Consumer<Instruction> instructionConsumer = instruction -> {
        if (instruction == null) {
            return;
        }
        final int type = instruction.getId();
        final byte[] data = instruction.getData();
        receiveIOCtrlData(type, data);
    };


    public void receiveIOCtrlData(final int type, final byte[] data) {
        if (type == AVIOCTRLDEFs.TCI_CMD_GET_ALARMTONE_CAP_RESP) {

            AlarmToneCapBean alarmToneCapBean = new AlarmToneCapBean();
            alarmToneCapBean.receiveIOCtrlData(data);
            audioCodecs = alarmToneCapBean.audioCodecs;
            TGLog.d(TAG,"audioCodecs = " + audioCodecs);
            soundHelper.setAlarmToneCapBean(alarmToneCapBean);
        }
    }

    @Override
    public void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//remove title bar  即隐藏标题栏
        hideActionBar();
        setContentView(R.layout.activity_custom_alert_sound);
        getIntentData();
        requestAudioPermission();
        initView();
        setListener();
    }

    private void registerICameraListener(){
        if (deviceFacade != null) {
            deviceFacade.observeConnectStatus(connectStatusConsumer);
            deviceFacade.getInstruct().observeOnReceive(instructionConsumer);
        }
    }

    private void unregisterICameraListener(){
        if (deviceFacade != null) {
            deviceFacade.unObserveConnectStatus(connectStatusConsumer);
            deviceFacade.getInstruct().unObserveOnReceive(instructionConsumer);
        }
    }

    private void getIntentData() {
        Intent intent = getIntent();
        audioCodecs = intent.getIntExtra(AlertSoundActivity.EXT_AUDIO_CODECS, 0);
        mFrom = intent.getStringExtra(AlertSoundListActivity.EXT_SOUND_LIST_FROM);
        audioRecorder = AudioRecorder.getInstance();
        soundHelper = AlertSoundHelper.getInstance();
        AlarmToneCapBean alarmToneCapBean = soundHelper.getAlarmToneCapBean();
        if (alarmToneCapBean != null && !alarmToneCapBean.getDataSuccess){
            info = intent.getParcelableExtra(DeviceSettingsActivity.EXT_DEVICE_INFO);
            deviceFacade = new DeviceFacade(info.uuid);
            registerICameraListener();
            deviceFacade.connect();
            if (deviceFacade != null) {
                if (deviceFacade.connected()){
                    AppHelper.sendIOCtrl(deviceFacade, AVIOCTRLDEFs.TCI_CMD_GET_ALARMTONE_CAP_REQ, new byte[4]);
                }else{
                    deviceFacade.connect();
                }
            }
        }
        TGLog.d(TAG,"audioCodecs = " + audioCodecs + ", mFrom = " + mFrom);
    }

    private void requestAudioPermission() {
        XXPermissions.with(this).permission(Permission.RECORD_AUDIO).request(new OnPermissionCallback() {
            @Override
            public void onGranted(List<String> permissions, boolean all) {
                //权限被允许
                hasAudioPermission = true;
            }

            @Override
            public void onDenied(List<String> permissions, boolean never) {
                MsgCenterToast.show(getBaseContext(), R.string.audio_permission_deny);
            }
        });
    }

    @Override
    protected void initView() {
        setToolBar();

        mAlertPersonalSoundItemView = findViewById(R.id.custom_view_personal);
        mAlertPersonalSoundItemView.setRecordAudioListener(this);

        mAlertPersonalSoundItemView.setFrom(mFrom);
        backClickEvent();

    }

    private void setToolBar() {
        modifyToolBar(R.string.alarm_sound_custom_set);
        TextView title = findViewById(R.id.device_name);
        title.setText("");
    }

    @Override
    protected boolean onBackClick() {
        if (isCompleted && !mAlertPersonalSoundItemView.isCustomSave()) {
            exitDialog();
            return false;
        }
        finishActivity();
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        checkPermission();
        if (LanguageUtils.isEnglish(CustomAlertSoundActivity.this)){
            modifyToolBar(R.string.add_voice);
        }else{
            modifyToolBar(R.string.txt_add_voice);
        }

    }

    private void finishActivity() {
        Intent intent = new Intent();
        intent.putExtra(AlertSoundActivity.EXT_CUSTOM_SET, mAlertPersonalSoundItemView.isCustomSave());
        setResult(RESULT_OK, intent);
    }

    private void setListener() {
        recordListener = data -> runOnUiThread(() -> {
            if (recorderStartTime == 0) {
                recorderStartTime = System.currentTimeMillis();
            } else {
                recorderTime = (System.currentTimeMillis() - recorderStartTime) / 1000 + 1;
            }
            TGLog.d(TAG,"recorderTime = " + recorderTime);
            mAlertPersonalSoundItemView.getRecorderTimeText().setText(String.valueOf(recorderTime > 6 ? 6 : recorderTime));
            if (recorderTime >= 4) {
                mAlertPersonalSoundItemView.getRecorderTimeText().setTextColor(getResources().getColor(R.color.alert_sound_custom_text_time_alert_color));
                if (recorderTime > 6) {
                    setCompletedLayoutShow();
                    return;
                }
            }
            toSavePcmFile(data);
            showWave(data);
            toSaveG711File(data);
        });

        mAlertPersonalSoundItemView.getBtnSave().setOnClickListener(v -> {
            if (mAlertPersonalSoundItemView.save()) {
                finishActivity();
                finish();
                TGToast.showToast(R.string.alert_sound_custom_save_completed);
            } else {
                TGToast.showToast(R.string.alert_sound_custom_save_failed);
            }
        });
    }

    private void toSavePcmFile(byte[] data) {
        TGLog.d(TAG,"toSavePcmFile audioCodecs " + audioCodecs);
        if (audioCodecs == AlarmUtil.TCMEDIA_AUDIO_PCM && !isCompleted) {
            File file = soundHelper.getTempFile(TGApplicationBase.getContext());
            TGLog.d("toSavePcmFile filePath =" + file.getAbsolutePath());
            FileUtil.wirteFile(file, data);
        }
    }

    private void toSaveG711File(byte[] data) {
        TGLog.d(TAG,"toSaveG711File audioCodecs " + audioCodecs);
        if (audioCodecs == AlarmUtil.TCMEDIA_AUDIO_G711A && !isCompleted) {
            File file = soundHelper.getTempFile(TGApplicationBase.getContext());
            TGLog.d(TAG,"toSaveG711File filePath =" + file.getAbsolutePath());
            int realBufferSize = data.length / 2;
            byte[] encoudeBuffer = new byte[realBufferSize];
            G711A mG711 = new G711A();
            mG711.encode(data, 0, realBufferSize * 2, encoudeBuffer);
            FileUtil.wirteFile(file, encoudeBuffer);
        }
    }

    private void showWave(byte[] data) {
        int length = data.length/2;
        short[] pcm = new short[length];
        ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(pcm);
        for (int i = 0; i < length; i += 60) {
            mAlertPersonalSoundItemView.addWaveData(pcm[i]);
        }
    }


    public void checkPermission() {
        if (!XXPermissions.isGranted(this, Permission.WRITE_EXTERNAL_STORAGE)) {
            String title =  ResourcesUtil.getString(com.module.appcommon.R.string.no_permission_to_work_with_screenvideo);
            String content =  ResourcesUtil.getString(com.module.appcommon.R.string.enable_permission_storage);
            PermissionUtil permissionUtil = new PermissionUtil(this);
            permissionUtil.checkPermissionFirst(Permission.WRITE_EXTERNAL_STORAGE, () -> {

            }, title, content);
        }

    }

    @Override
    public void onPause() {
        super.onPause();
        if (audioRecorder != null) {
            audioRecorder.pauseRecord();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (audioRecorder != null) {
            audioRecorder.release();
        }
        mAlertPersonalSoundItemView.releaseMediaPlayer();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterICameraListener();
        File file = soundHelper.getTempFile(TGApplicationBase.getContext());
        if (file.exists()) {
            FileUtil.delete(file.getAbsolutePath());
        }
    }

    private void setCompletedLayoutShow() {
        mAlertPersonalSoundItemView.setCustomSave(false);
        mAlertPersonalSoundItemView.setButtonEnable(true);
        if (!isCompleted) {
            File file = soundHelper.getTempFile(TGApplicationBase.getContext());
            if (file.exists()) {
                soundHelper.setWaveFileHeader(file);
            }
            isCompleted = true;
        }
    }

    @Override
    public void onRecordStart() {
        if (XXPermissions.isGranted(this, Permission.RECORD_AUDIO)) {
            if (XXPermissions.isGranted(this, Permission.WRITE_EXTERNAL_STORAGE)) {
                if (audioRecorder != null) {
                    if (audioRecorder.getStatus() == AudioRecorder.Status.STATUS_NO_READY) {
                        audioRecorder.createDefaultAudio();
                        if (recordListener != null) {
                            TGLog.d(TAG,"recordListener "  + recordListener);
                            audioRecorder.startRecord(recordListener);
                        }
                    } else if (audioRecorder.getStatus() == AudioRecorder.Status.STATUS_PAUSE) {
                        if (recordListener != null) {
                            TGLog.d(TAG,"recordListener "  + recordListener);
                            audioRecorder.startRecord(recordListener);
                        }
                    }
                }

            } else {
                MsgCenterToast.show(this, R.string.no_storage_permission);
            }
        } else {
            MsgCenterToast.show(this, R.string.audio_permission_deny);
        }
        recorderStartTime = 0;
        recorderTime = 0;
        setRecordTimeInfo(R.color.alert_sound_custom_text_color);
        mAlertPersonalSoundItemView.getWaveView().setVisibility(View.VISIBLE);

        File file = soundHelper.getTempFile(TGApplicationBase.getContext());
        if (file.exists()) {
            TGLog.d(TAG,"file path = " + file.getAbsolutePath());
            FileUtil.delete(file.getPath());
        }
        isCompleted = false;
    }

    private void setRecordTimeInfo(@ColorRes int id) {
        mAlertPersonalSoundItemView.getRecorderTimeText().setText(String.valueOf(recorderTime));
        mAlertPersonalSoundItemView.getRecorderTimeText().setTextColor(getResources().getColor(id));
    }

    @Override
    public void onRecordStop() {
        if (hasAudioPermission) {
            if (audioRecorder != null && audioRecorder.getStatus() == AudioRecorder.Status.STATUS_START) {
                audioRecorder.pauseRecord();
            }
        }
        mAlertPersonalSoundItemView.getWaveView().setVisibility(View.GONE);
        if (recorderTime > 0) {
            setCompletedLayoutShow();
        }
    }

    private void exitDialog() {
        new TGAlertDialog(this).builder().setTitle(R.string.alert_sound_custom_exit).setMessage(getString(R.string.alert_sound_custom_not_save))
                .setPositiveButton(R.string.confirm, v -> finish()).setNegativeButton(getString(R.string.cancel), v -> {
        }).show();
    }
}